import ParticleSystem from '../js/particle-system.esm.js';
import { PrimitivePlaneShader } from '../js/primitive-plane-shader.esm.js';

// @ts-ignore
const Color = Cesium.Color;

const defaultColorRange = [
  // rgba(127, 1, 131, 255)
  Color.fromBytes(127, 1, 131, 255),
  // rgba(85, 1, 171, 255)
  Color.fromBytes(85, 1, 171, 255),
  // rgba(40, 0, 212, 255)
  Color.fromBytes(40, 0, 212, 255),
  // rgba(2, 1, 253, 255)
  Color.fromBytes(2, 1, 253, 255),
  // rgba(2, 56, 226, 255)
  Color.fromBytes(2, 56, 226, 255),
  // rgba(1, 109, 194, 255)
  Color.fromBytes(1, 109, 194, 255),
  // rgba(2, 167, 167, 255)
  Color.fromBytes(2, 167, 167, 255),
  // rgba(0, 196, 108, 255)
  Color.fromBytes(0, 196, 108, 255),
  // rgba(0, 226, 57, 255)
  Color.fromBytes(0, 226, 57, 255),
  // rgba(0, 255, 0, 255)
  Color.fromBytes(0, 255, 0, 255),
  // rgba(84, 255, 1, 255)
  Color.fromBytes(84, 255, 1, 255),
  // rgba(171, 255, 1, 255)
  Color.fromBytes(171, 255, 1, 255),
  // rgba(255, 255, 3, 255)
  Color.fromBytes(255, 255, 3, 255),
  // rgba(255, 171, 2, 255)
  Color.fromBytes(255, 171, 2, 255),
  // rgba(253, 85, 3, 255)
  Color.fromBytes(253, 85, 3, 255),
  // rgba(254, 1, 3, 255)
  Color.fromBytes(254, 1, 3, 255)
];

export default class Wind3D {
  /**
   *
   * @param {import('cesium').Viewer} viewer
   * @param {import('./panel.esm.js').default} panel
   * @param {object} inputData
   * @param {*} inputData.particleData
   * @param {*} inputData.thematicData
   * @param {*} inputData.triangleData
   */
  constructor(viewer, panel, inputData) {
    this.thematicData = inputData.thematicData;
    this.triangleData = inputData.triangleData;

    this.viewer = viewer;
    this.scene = this.viewer.scene;
    this.camera = this.viewer.camera;
    this.colorRange = defaultColorRange;
    this.panel = panel;

    this.viewerParameters = {
      // @ts-ignore
      lonRange: new Cesium.Cartesian2(),
      // @ts-ignore
      latRange: new Cesium.Cartesian2(),
      pixelSize: 0.0
    };

    /* 设置初始视角 */
    this.viewer.scene.camera.setView({
      // @ts-ignore
      destination: new Cesium.Cartesian3(-2475064.4457, 5614495.12, 2511055.56),
      orientation: {
        heading: 6.144,
        pitch: -1.567, // 初始倾角不能过大，最好垂直的
        roll: 0
      }
    });

    // use a smaller earth radius to make sure distance to camera > 0
    // @ts-ignore
    this.globeBoundingSphere = new Cesium.BoundingSphere(Cesium.Cartesian3.ZERO, 0.99 * 6378137.0);
    this.updateViewerParameters();

    const userInputParams = this.panel.getUserInput();
    this.particleSystem = new ParticleSystem(
      // @ts-ignore
      this.scene.context,
      inputData.particleData,
      userInputParams,
      this.viewerParameters
    );
    this.addPrimitives();
    this.setupEventListeners();

    this.imageryLayers = this.viewer.imageryLayers;
  }

  addPrimitives() {
    // the order of primitives.add() should respect the dependency of primitives
    this.scene.primitives.add(this.particleSystem.particlesComputing.primitives.calculateSpeed);
    this.scene.primitives.add(this.particleSystem.particlesComputing.primitives.updatePosition);
    this.scene.primitives.add(
      this.particleSystem.particlesComputing.primitives.postProcessingPosition
    );

    this.scene.primitives.add(this.particleSystem.particlesRendering.primitives.segments);
    this.scene.primitives.add(this.particleSystem.particlesRendering.primitives.trails);
    this.scene.primitives.add(this.particleSystem.particlesRendering.primitives.screen);
    const primitivePlaneShader = new PrimitivePlaneShader({ viewer: this.viewer });

    primitivePlaneShader.createPrimitive(
      {
        renderData: this.thematicData,
        triangleData: this.triangleData
      },
      'Layer_1',
      this.colorRange
    );
  }

  updateViewerParameters() {
    this.viewerParameters.lonRange.x = 114.2641848923519916; // lonLatRange.lon.min;
    this.viewerParameters.lonRange.y = 113.3245601336276565; //lonLatRange.lon.max;
    this.viewerParameters.latRange.x = 22.0021053095437118; // lonLatRange.lat.min;
    this.viewerParameters.latRange.y = 22.8137807481400863; //lonLatRange.lat.max;

    var pixelSize = this.camera.getPixelSize(
      this.globeBoundingSphere,
      this.scene.drawingBufferWidth,
      this.scene.drawingBufferHeight
    );

    if (pixelSize > 0) {
      this.viewerParameters.pixelSize = pixelSize;
    }
  }

  setupEventListeners() {
    const that = this;

    this.camera.moveStart.addEventListener(function () {
      that.scene.primitives.show = false;
    });

    this.camera.moveEnd.addEventListener(function () {
      that.updateViewerParameters();
      that.particleSystem.applyViewerParameters(that.viewerParameters);
      that.scene.primitives.show = true;
    });

    var resized = false;
    window.addEventListener('resize', function () {
      resized = true;
      that.scene.primitives.show = false;
      that.scene.primitives.removeAll();
    });

    this.scene.preRender.addEventListener(function () {
      if (resized) {
        // @ts-ignore
        that.particleSystem.canvasResize(that.scene.context);
        resized = false;
        that.addPrimitives();
        that.scene.primitives.show = true;
      }
    });

    window.addEventListener('particleSystemOptionsChanged', function () {
      that.particleSystem.applyUserInput(that.panel.getUserInput());
    });
  }

  debug() {
    const that = this;

    var animate = function () {
      that.viewer.resize();
      that.viewer.render();
      requestAnimationFrame(animate);
    };
    animate();
  }

  dispose() {
    this.scene.primitives.remove(this.particleSystem.particlesComputing.primitives.calculateSpeed);
    this.scene.primitives.remove(this.particleSystem.particlesComputing.primitives.updatePosition);
    // prettier-ignore
    this.scene.primitives.remove(this.particleSystem.particlesComputing.primitives.postProcessingPosition);

    this.scene.primitives.remove(this.particleSystem.particlesRendering.primitives.segments);
    this.scene.primitives.remove(this.particleSystem.particlesRendering.primitives.trails);
    this.scene.primitives.remove(this.particleSystem.particlesRendering.primitives.screen);
  }
}
